#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re
from decimal import Decimal
from django import template
from django.template import Library

register = Library()

def moneyfmt(value, places=2, curr='', sep=',', dp='.',
             pos='', neg='-', trailneg=''):
    """Convert Decimal to a money formatted string.

    places:  required number of places after the decimal point
    curr:    optional currency symbol before the sign (may be blank)
    sep:     optional grouping separator (comma, period, space, or blank)
    dp:      decimal point indicator (comma or period)
             only specify as blank when places is zero
    pos:     optional sign for positive numbers: '+', space or blank
    neg:     optional sign for negative numbers: '-', '(', space or blank
    trailneg:optional trailing minus indicator:  '-', ')', space or blank

    >>> d = Decimal('-1234567.8901')
    >>> moneyfmt(d, curr='$')
    '-$1,234,567.89'
    >>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-')
    '1.234.568-'
    >>> moneyfmt(d, curr='$', neg='(', trailneg=')')
    '($1,234,567.89)'
    >>> moneyfmt(Decimal(123456789), sep=' ')
    '123 456 789.00'
    >>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
    '<0.02>'

    """
    q = Decimal(10) ** -places      # 2 places --> '0.01'
    sign, digits, exp = value.quantize(q).as_tuple()
    result = []
    digits = map(str, digits)
    build, next = result.append, digits.pop
    if sign:
        build(trailneg)
    for i in range(places):
        build(next() if digits else '0')
    build(dp)
    if not digits:
        build('0')
    i = 0
    while digits:
        build(next())
        i += 1
        if i == 3 and digits:
            i = 0
            build(sep)
    build(curr)
    build(neg if sign else pos)
    return ''.join(reversed(result))


@register.filter
def moneyfmt(value, args=None):
    """
    Денежный формат

    args `places=2|sep=,`
    """
    if value:
        if args:
            args = dict([arg.split('=') for arg in args.split('|')])
        value = moneyfmt(Decimal(value), **args) if args else moneyfmt(Decimal(value))
    return value


class ColumnsNode(template.Node):
    def __init__(self, iterable, num, var_name):
        self.iterable = template.Variable(iterable)
        self.num = num
        self.var_name = var_name
        
    def render(self, context):
        iterable = list(self.iterable.resolve(context))
        num = self.num
        length = len(iterable)
        if iterable and length / num >= 1:
            x,y = divmod(length, num)
            newlst = []
            while iterable:
                if y:
                    i = x+1
                    y-=1
                else:
                    i = x
                newlst.append(iterable[:i])
                del iterable[:i]
            context[self.var_name] = newlst
        else:
            context[self.var_name] = [iterable]
        return ''

    
def columns(parser, token):
    """
    Разбивает последовательность объектов на колонки

    lst - последовательность объектов
    num - количество столбцов
    """
    try:
        tag_name, arg = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0]
    m = re.search(r'(.*?) (\d*?) as (\w+)', arg)
    if not m:
        raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name
    iterable, num, var_name = m.groups()
    try:
        num = int(num)
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag's argument %s not integer" % (tag_name, num)
    return ColumnsNode(iterable, num, var_name)

columns = register.tag(columns)